﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Windows.Markup;

namespace System.Windows.Media.Media3D10
{
    /// <summary>
    /// Fournit un <see cref="Visual3D10"/> qui restitue les objets <see cref="Model3D10"/>. 
    /// </summary>
    [ContentProperty("Children")]
    public class ModelVisual3D10 : Visual3D10
    {
        #region Dependency Properties
        /// <summary>
        /// Identifie la propriété de dépendance <see cref="Content"/>.
        /// </summary>
        public static readonly DependencyProperty ContentProperty = 
            DependencyProperty.Register("Content", typeof(Model3D10), typeof(ModelVisual3D10));

        /// <summary>
        /// Identifie la propriété de dépendance <see cref="Transform"/>.
        /// </summary>
        public static readonly DependencyProperty TransformProperty =
            DependencyProperty.Register("Transform", typeof(Transform3D10), typeof(ModelVisual3D10));
        #endregion

        #region Constructors
        /// <summary>
        /// Initialise une nouvelle instance de la classe <see cref="ModelVisual3D10"/>
        /// </summary>
        public ModelVisual3D10()
            : base()
        {
            this.Transform = Transform3D10.Identity;
            this.Children = new Visual3D10Collection();
        }
        #endregion

        #region Public Properties
        /// <summary>
        /// Obtient une collection d'objets <see cref="Visual3D10"/> enfants.
        /// </summary>
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public Visual3D10Collection Children { get; private set; }

        /// <summary>
        /// Obtient ou définit le modèle qui décrit le contenu de <see cref="ModelVisual3D10"/>.
        /// </summary>
        public Model3D10 Content 
        {
            get { return (Model3D10)GetValue(ContentProperty); }
            set { SetValue(ContentProperty, value); }
        }

        /// <summary>
        /// Obtient ou définit les éléments de transformation appliqués à <see cref="ModelVisual3D10"/>.
        /// </summary>
        public Transform3D10 Transform
        {
            get { return (Transform3D10)GetValue(TransformProperty); }
            set { SetValue(TransformProperty, value); }
        }
        #endregion

        #region Visual3D10 Implementation
        /// <summary>
        /// En cas de substitution dans une classe dérivée, participe au dessin des objets dans le pipeline DirectX10
        /// </summary>
        /// <param name="context">Contexte de dessin.</param>
        /// <exception cref="ArgumentNullException">Soulevée si le contexte est null.</exception>
        protected internal override void OnDraw(DrawingContext context)
        {
            if (context == null) throw new ArgumentNullException("context");

            SlimDX.Matrix world = context.WorldMatrix * Transform.Value;
            context.WorldMatrix = world;
            if (this.Content != null) (this.Content as IDrawable).Draw(context);

            foreach (IDrawable item in Children)
            {
                context.WorldMatrix = world;
                item.Draw(context);
            }
        }
        #endregion
    }
}
